//
//  EmoticonViewModel.swift
//  01-表情键盘
//
//  Created by Apple on 15/9/30.
//  Copyright © 2015年 itcast. All rights reserved.
//

import UIKit

/// 表情视图模型
class EmoticonViewModel {
    
    /// 单例 － 目的：保证表情包的数据只被从plist加载一次
    static let sharedViewModel = EmoticonViewModel()
    
    /// 表情包数组
    lazy var packages = [EmoticonPackage]()
    
    /// 构造函数 - 创建的同时，加载数据
    private init() {
        loadEmoticons()
    }
    
    /// 将 emoticon 对象添加到最近使用的表情
    func favorite(em: Emoticon) {
        // 1. 使用次数增加
        em.times++
        
        // 2. 判断表情是否已经在数组中，插入表情
        if !packages[0].emoticons.contains(em) {
            // 将表情插入到第一位
            packages[0].emoticons.insert(em, atIndex: 0)
            
            // 删除倒数第二个表情
            packages[0].emoticons.removeAtIndex(packages[0].emoticons.count - 2)
        }
        
        // 3. 对数组进行排序
//        packages[0].emoticons.sortInPlace { (obj0, obj1) -> Bool in
//            return obj0.times > obj1.times
//        }
        // 简写的特点，有返回值，只有一句代码
        packages[0].emoticons.sortInPlace { $0.times > $1.times }
        
        print(packages[0].emoticons)
        print(packages[0].emoticons.count)
    }
    
    /// 将指定 纯文本字符串，转换为带表情图片的属性文本
    ///
    /// - parameter string: string
    /// - parameter font:   font
    ///
    /// - returns: 属性字符串
    func emoticonText(string: String, font: UIFont) -> NSAttributedString {
        
        // 使用 string 建立属性文本
        let attrText = NSMutableAttributedString(string: string)
        
        // 1. 利用正则表达式，过滤出表情符号文本
        // 注意：[] 是正则表达式的保留字，如果需要使用，需要转义
        let pattern = "\\[.*?\\]"
        let regex = try! NSRegularExpression(pattern: pattern, options: [])
        
        let matches = regex.matchesInString(string, options: [], range: NSRange(location: 0, length: string.characters.count))
        
        // 2. 记录找到的匹配数量
        var count = matches.count
        
        // 3. `倒着`遍历字符串的范围
        while count > 0 {
            let range = matches[--count].rangeAtIndex(0)
            
            // 1> 根据 range 获取的表情文本
            let emText = (string as NSString).substringWithRange(range)
            
            // 2> 根据表情文本，查找表情对象
            if let em = emoticonWithString(emText) {
                
                // 3> 根据表情符号，创建属性文本
                let imageText = EmoticonAttachment.emotionText(em, font: font)
                
                // 4> 替换属性文本
                attrText.replaceCharactersInRange(range, withAttributedString: imageText)
            }
        }
        
        return attrText
    }
    
    /// 根据指定的表情符号查找表情对象
    private func emoticonWithString(string: String) -> Emoticon? {
        
        // 1. 遍历表情包数组
        for p in EmoticonViewModel.sharedViewModel.packages {
            
            // 2. 在 emoticons 数组中查找指定字符串的表情是否存在
            let em = p.emoticons.filter() { $0.chs == string }.last
            
            // 3. 判断是否找到
            if em != nil {
                return em
            }
        }
        
        return nil
    }
    
    /// 加载表情
    /**
        1. 读取 emoticons.plist，知道所有的 表情包
        2. 根据 表情包中的目录名，分别加载 info.plist
        3. 创建每个表情包的模型
    */
    private func loadEmoticons() {
        // 0. 添加默认分组
        packages.append(EmoticonPackage(dict: ["group_name_cn": "最近XXX"]))
        
        // 1. 读取 emoticons.plist，提示如果路径不存在，会直接返回nil
        let path = NSBundle.mainBundle().pathForResource("emoticons.plist", ofType: nil, inDirectory: "Emoticons.bundle")!
        
        // 2. 加载字典
        let dict = NSDictionary(contentsOfFile: path)
        
        // 3. 从字典中获得 id 的数组
        // valueForKey是 KVC 的函数，能够直接将 NSArray 中需要的 key 取出建立新的数组
        let array = (dict!["packages"] as! NSArray).valueForKey("id") as! [String]
        
        // 4. 遍历 array 加载 info.plist
        for dir in array {
            // 1> 获取 info.plist 路径
            let infoPath = NSBundle.mainBundle().pathForResource("info.plist", ofType: nil, inDirectory: "Emoticons.bundle/" + dir)!
            
            // 2> 加载 plist，字典转模型
            let packageDict = NSDictionary(contentsOfFile: infoPath) as! [String: AnyObject]
            
            packages.append(EmoticonPackage(dict: packageDict))
        }
    }
}